﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MovieRental.DataInterfaces;
using MovieRental.SqlRepositoryLibrary.Configuration;
using System.Configuration;
using System.Data.SqlClient;
using System.IO;
using System.Text.RegularExpressions;
using System.Data;

namespace MovieRental.SqlRepositoryLibrary
{
    public class SqlRepositoryFactory : IRepositoryFactory
    {
        private string _connectionString;
        private const string _defaultDbName = "MovieRentalDB";

        public SqlRepositoryFactory()
        {
            SqlRepositoryConfiguration config = (SqlRepositoryConfiguration)ConfigurationManager.GetSection("sqlRepositoryConfiguration");
            _connectionString = BuildConnectionString(config);
            TestConnection(_connectionString, config);
        }

        private string BuildConnectionString(SqlRepositoryConfiguration config)
        {
            var sqlConnectionString = new SqlConnectionStringBuilder()
            {
                DataSource = config.Connection.Server,
                InitialCatalog = config.Connection.Database,
                UserID = config.Connection.User,
                Password = config.Connection.Password,
                Pooling = config.Connection.Pooling
            };
            sqlConnectionString.ConnectTimeout = 10;
            sqlConnectionString.IntegratedSecurity = string.IsNullOrEmpty(config.Connection.User);
            return sqlConnectionString.ToString();
        }

        private void TestConnection(string connectionString, SqlRepositoryConfiguration config)
        {
            if (config.Mode == InitializationMode.Open)
            {
                SqlConnection connection = new SqlConnection(_connectionString);
                connection.Open();
                connection.Close();
            }
            if (config.Mode == InitializationMode.DropCreate)
            {
                SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder(_connectionString);
                builder.InitialCatalog = "master";
                SqlConnection.ClearAllPools();
                SqlConnection connection = new SqlConnection(builder.ToString());
                connection.Open();
                ExecuteSqlFromFile(connection, config.DbCreationFileName, config.Connection.Database);
                connection.Close();
            }
   
        }

        private void ExecuteSqlFromFile(SqlConnection connection, string fileName, string dbName)
        {
            string sql = File.ReadAllText(fileName);
            if (!dbName.Equals(_defaultDbName, StringComparison.OrdinalIgnoreCase))
                sql = Regex.Replace(sql, "MovieRentalDb", dbName, RegexOptions.IgnoreCase);
            

            Regex regex = new Regex("^GO", RegexOptions.IgnoreCase | RegexOptions.Multiline);
            string[] lines = regex.Split(sql);

            using (SqlCommand cmd = connection.CreateCommand())
            {
                cmd.Connection = connection;

                foreach (string line in lines)
                {
                    if (line.Length > 0)
                    {
                        cmd.CommandText = line;
                        cmd.CommandType = CommandType.Text;
                        cmd.ExecuteNonQuery();
                    }
                }
            }
        }

        public void Reconnect()
        {
            SqlRepositoryConfiguration config = (SqlRepositoryConfiguration)ConfigurationManager.GetSection("sqlRepositoryConfiguration");
            _connectionString = BuildConnectionString(config);
            TestConnection(_connectionString, config);
        }

        public ICartDiscountRepository GetCartDiscountRepository()
        {
            return new SqlCartDiscountRepository(_connectionString);
        }

        public ICustomerRepository GetCustomerRepository()
        {
            return new SqlCustomerRepository(_connectionString);
        }

        public IEditionRepository GetEditionRepository()
        {
            return new SqlEditionRepository(_connectionString);
        }

        public ILoanCartRepository GetLoanCartRepository()
        {
            return new SqlLoanCartRepository(_connectionString);
        }

        public IMediaTypeRepository GetMediaTypeRepository()
        {
            return new SqlMediaTypeRepository(_connectionString);
        }

        public IMovieRepository GetMovieRepository()
        {
            return new SqlMovieRepository(_connectionString);
        }

        public IPersonalDiscountRepository GetPersonalDiscountRepository()
        {
            return new SqlPersonalDiscountRepository(_connectionString);
        }

        public ITemporaryDiscountRepository GetTemporaryDiscountRepository()
        {
            return new SqlTemporaryDiscountRepository(_connectionString);
        }
    }
}
